#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <string>
#include <fstream>
#include <streambuf>
#include <sstream>
#include <cstdlib>
#include <new>
#include <typeinfo>
#include <list>
#include <thread> // std::thread
#include <mutex>  // std::mutex

using namespace std;

// 参考: https://blog.csdn.net/misayaaaaa/article/details/53786215
// 参考: https://github.com/applenob/Cpp_Primer_Practice/blob/master/excersize/ch09.md
// chapter 9

// 1. 对于下面的程序任务，vector、deque和list哪种容器最为适合？解释你的选择的理由。如果没有哪一种容器优于其他容器，也请解释理由。

(a) 读取固定数量的单词，将它们按字典序插入到容器中。我们将在下一章中看到，关联容器更适合这个问题。
(b) 读取未知数量的单词，总是将单词插入到末尾。删除操作在头部进行。
(c) 从一个文件读取未知数量的整数。将这些数排序，然后将它们打印到标准输出。
解：

(a) list ，因为需要频繁的插入操作。
(b) deque ，总是在头尾进行插入、删除操作。
(c) vector ，不需要进行插入删除操作。

知识点1：几种顺序容器的特点

vector：可变大小，支持快速随机访问，尾部插入数据很快

deque：双端队列。支持快速随机访问，头部插入数据很快

list：双向链表。支持双向顺序访问，在其任何位置插入删除数据都很快

array：固定大小数组，不能改变大小。(注意这里与普通的内置数组类型是不一样的)

string：与vector类似，专用于保存字符。

知识点2：在通常情况下，使用vector是非常好的选择。且新版本的标准库容器比旧版本快很多。C++程序应该使用标准库容器，而不是原始的数据结构如：内置数组。



(a)list，因为可能需要在容器的中间位置插入元素

(b)deque，因为需要在头部进行元素的删除，deque效率更高

(c)vector，无具体的删除插入操作，未知数量，vector是个不错的选择。





// 2. 定义一个list对象，其元素类型是int的deque。

解：
知识点1：容器中的元素类型可以是另一个容器

知识点2：本节中的几个比较重要的容器操作：

c.empty()：c中存储了元素，返回false.

c.cbegin()：返回const_iterator

c.clear()：清空容器

list<deque<int>>;//旧版本的编译器需要在两个尖括号中加空格


// 3.
知识点1：限制如下：

迭代器指向同一个容器或者最后一个元素之后的位置

可以反复递增begin直到end

知识点2：迭代器指向的元素范围是左闭合区间，注意end指向的是最后一个元素之后的位置。

[begin , end)




// 4.



// 10. 下面4个对象分别是什么类型？

vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(), it2 = v2.begin();
auto it3 = v1.cbegin(), it4 = v2.cbegin();

it1：vector<int>::iterator

it2：const vector<int>::iterator

it3：vector<int>::const_iterator

it4：const vector<int>::const_iterator


// 11.

对6种创建和初始化vector对象的方法，每一种都给出一个实例。解释每个vector包含什么值。

解：

vector<int> vec;    // 0
vector<int> vec(10);    // 10个0
vector<int> vec(10, 1);  // 10个1
vector<int> vec{ 1, 2, 3, 4, 5 }; // 1, 2, 3, 4, 5
vector<int> vec(other_vec); // 拷贝 other_vec 的元素
vector<int> vec(other_vec.begin(), other_vec.end()); // 拷贝 other_vec 的元素


// 12.对于接受一个容器创建其拷贝的构造函数，和接受两个迭代器创建拷贝的构造函数，解释它们的不同。

解：

接受一个容器创建其拷贝的构造函数，必须容器类型和元素类型都相同。
接受两个迭代器创建拷贝的构造函数，只需要元素的类型能够相互转换，容器类型和元素类型可以不同
接受迭代器创建拷贝，拷贝的是两个迭代器之间的内容，而直接接受一个容器，就是拷贝整个容器的内容了




// 13. 如何从一个list<int>初始化一个vector<double>？从一个vector<int>又该如何创建？编写代码验证你的答案。

解：

list<int> ilst(5, 4);
vector<int> ivc(5, 5);

vector<double> dvc(ilst.begin(), ilst.end());
vector<double> dvc2(ivc.begin(), ivc.end());




// 14.
编写程序，将一个list中的char *指针元素赋值给一个vector中的string。

解：

    std::list<const char*> l{ "hello", "world" };
    std::vector<std::string> v;
    v.assign(l.cbegin(), l.cend());





// 16. 重写上一题的程序，比较一个list中的元素和一个vector中的元素。

解：

    std::list<int>      li{ 1, 2, 3, 4, 5 };
    std::vector<int>    vec2{ 1, 2, 3, 4, 5 };
    std::vector<int>    vec3{ 1, 2, 3, 4 };

    std::cout << (std::vector<int>(li.begin(), li.end()) == vec2 ? "true" : "false") << std::endl;
    std::cout << (std::vector<int>(li.begin(), li.end()) == vec3 ? "true" : "false") << std::endl;



//17.  假定c1和c2是两个容器，下面的比较操作有何限制？

解：

	if (c1 < c2)
c1和c2必须是相同类型的容器并且保存相同类型的元素
元素类型要支持关系运算符


// 26.
使用下面代码定义的ia，将ia拷贝到一个vector和一个list中。是用单迭代器版本的erase从list中删除奇数元素，从vector中删除偶数元素。

int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
解：

vector<int> vec(ia, end(ia));
list<int> lst(vec.begin(), vec.end());

for (auto it = lst.begin(); it != lst.end(); )
	if (*it & 0x1)
		it = lst.erase(it);
	else 
		++it;

for (auto it = vec.begin(); it != vec.end(); )
	if (!(*it & 0x1))
		it = vec.erase(it);
	else
		++it;			






// 29. 假定vec包含25个元素，那么vec.resize(100)会做什么？如果接下来调用vec.resize(10)会做什么？

解：

将75个值为0的元素添加到vec的末尾
从vec的末尾删除90个元素
知识点：resize()改变容器的大小，多删少补并初始化，需要默认初始化的，则需要参数类型有默认构造函数。

resize(100)会将其大小改为100个元素的大小，添加新元素并初始化，之后使用resize(10)会将之后的90个元素舍弃







// 32.在第316页的程序中，向下面语句这样调用insert是否合法？如果不合法，为什么？

iter = vi.insert(iter, *iter++);
解：

不合法。因为参数的求值顺序是未指定的

不合法，首先明确运算符的顺序：++高于*解引用符号，这样就不是复制当前元素了，复制的是奇数后面的一个数。失去了原有的意义




// 35. 解释一个vector的capacity和size有何区别。

解：

capacity的值表明，在不重新分配内存空间的情况下，容器可以保存多少元素
而size的值是指容器已经保存的元素的数量



// 37. 为什么list或array没有capacity成员函数？

解：

因为list是链表，而array不允许改变容器大小
vector中的元素在内存中是连续存放的，所以需要capacity这个东西~

list没有capacity是因为其存储元素的内存是不连续的，不需要capacity

array是因为其大小是固定的




// 




int main()
{
   
    printf("hello c++ \n");
}